package com.xinxing.learning.security.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;

/**
 * 自定义授权服务器配置
 */
// @Configuration
// 指定当前应用为授权服务器
// @EnableAuthorizationServer
public class InMemoryAuthorizationServer extends AuthorizationServerConfigurerAdapter {

    private final PasswordEncoder passwordEncoder;

    private final UserDetailsService userDetailsService;

    private final AuthenticationManager authenticationManager;

    @Autowired
    public InMemoryAuthorizationServer(PasswordEncoder passwordEncoder, UserDetailsService userDetailsService, AuthenticationManager authenticationManager) {
        this.passwordEncoder = passwordEncoder;
        this.userDetailsService = userDetailsService;
        this.authenticationManager = authenticationManager;
    }


    /**
     * 配置授权服务器可以为哪些客户端授权
     * 客户端id clientId
     * 客户端秘钥 secret
     * 重定向地址 redirect-url
     * 授权模式 authorization-type
     *
     * @param clients
     * @throws Exception
     */
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory()
                .withClient("client")
                .secret(passwordEncoder.encode("secret"))
                .redirectUris("https://www.baidu.com")
                // 授权码模式: authorization_code 刷新令牌: refresh_token 简化模式: implicit 密码模式: password 客户端模式: client_credentials
                // 目前不支持简化模式
                .authorizedGrantTypes("authorization_code", "refresh_token", "implicit", "password", "client_credentials")
                // 令牌运行获取的资源权限
                .scopes("read:user")
        ;
        // 授权码模式
        // 1.请求用户是否授权 /oauth/authorize
        // 完整路径: GET http://localhost:8080/oauth/authorize?client_id=client&response_type=code&redirect_uri=https://www.baidu.com
        // 2.授权之后跟进获取的授权码获取令牌 /oauth/token
        // 完整路径: curl -X POST -H "Content-Type: application/x-www-form-urlencoded" -d 'grant_type=authorization_code&code=zRRKA2&redirect_uri=https://www.baidu.com' http://client:secret@localhost:8080/oauth/token
        // 刷新令牌 /oauth/token
        // 完整路径: curl -X POST -H "Content-Type: application/x-www-form-urlencoded" -d 'grant_type=refresh_token&refresh_token=zRRKA2&client_id=client' http://client:secret@localhost:8080/oauth/token
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        // 刷新令牌
        endpoints.userDetailsService(userDetailsService);
        // 密码模式
        endpoints.authenticationManager(authenticationManager);
    }

}
